package remy;

import Engine.src.ca.uqac.dim.turtledb.*;
import java.util.ArrayList;

public class QueryTranslator {

    public static Relation translate(String q) {
        try {
                ArrayList<String> selectElts = segmentQuery(q, "SELECT", "FROM", ",");		
                ArrayList<String> fromElts = segmentQuery(q, "FROM", "WHERE", ",");
                ArrayList<String> whereElts = segmentQuery(q, "WHERE", ";", "AND");

                Schema sch = new Schema();
                for(String select : selectElts){
                        sch.add(new Attribute(select));
                }

                Product product = new Product();
                for(String from : fromElts){			
                        product.addOperand(new VariableTable(from));
                }

                Condition cond = createCondition(whereElts);

                Selection selection = null;
                if(cond != null){
                        selection = new Selection(cond, product);
                }

                Projection projection = null;
                if(selection == null){
                        projection = new Projection(sch, product);
                }
                else{
                        projection = new Projection(sch, selection);
                }

                return projection;
        } catch (QueryTranslatorException e) {
                e.printStackTrace();
                return null;
        }
    }

    private static Equality createEquality(String s){
        Equality equal = null;

        String[] elts = s.split("=");
        if(elts.length == 2){
                equal = new Equality(new Attribute(elts[0].trim()), new Value(elts[1].trim()));
        }

        return equal;
    }

    private static LogicalOr createLogicalOr(String s){
        LogicalOr or = null;

        String str = s;
        if(s.startsWith("(") && s.endsWith(")")){
                str = s.substring(1, s.length()-1);
        }

        String[] elts = str.split("OR");

        if(elts.length > 0){
                or = new LogicalOr();

                for(String elt : elts){
                        Equality cond = createEquality(elt);

                        if(cond != null){
                                or.addCondition(cond);
                        }
                }		
        }		

        return or;
    }

    private static Condition createCondition(ArrayList<String> whereElts){
        Condition cond = null;

        if(!whereElts.isEmpty()){
                if(whereElts.size() == 1){
                        if(whereElts.get(0).contains("OR")){
                                cond = createLogicalOr(whereElts.get(0));
                        }
                        else{
                                cond = createEquality(whereElts.get(0));
                        }
                }
                else{
                        cond = new LogicalAnd();

                        for(String elt : whereElts){
                                if(elt.contains("OR") && elt.startsWith("(") && elt.endsWith(")")){
                                        ((NAryCondition) cond).addCondition(createLogicalOr(elt));
                                }
                                else{
                                        ((NAryCondition) cond).addCondition(createEquality(elt));
                                }
                        }
                }
        }

        return cond;
    }

    private static ArrayList<String> segmentQuery(String query, String start, String end, String symbol)
                    throws QueryTranslatorException {
        if(symbol.isEmpty()){
                throw new QueryTranslatorException("Erreur paramètre symbole de segmentation");
        }

        int startIndex = query.toLowerCase().indexOf(start.toLowerCase());
        int endIndex = query.toLowerCase().indexOf(end.toLowerCase());

        if(startIndex == -1 || endIndex == -1) {
                throw new QueryTranslatorException("Impossible de segmenter la requête");
        }

        startIndex += start.length();
        ArrayList<String> segments = new ArrayList<String>();

        for ( String segment : query.substring(startIndex, endIndex).split(symbol) ) {
                if(!segment.trim().isEmpty()){
                        segments.add(segment.trim());	
                }
                else{
                        throw new QueryTranslatorException("Format de la requête incorrect");
                }
        }

        return segments;
    }	
}

class QueryTranslatorException extends Exception {

    public QueryTranslatorException(){
        super();
    }

    public QueryTranslatorException(String s){
        super(s);
    }

}
